package managedbean.Production;

import entity.AccessRole;
import entity.ConsolidatedMthSalesFc;
import entity.Employee;
import entity.IndependentVariable;
import entity.Product;
import entity.ProductionSchedule;
import entity.ProductionScheduleDay;
import entity.SalesForecast;
import entity.SalesHistory;
import flanagan.analysis.Regression;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.RequestScoped;
import javax.ejb.EJB;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedProperty;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;
import managedbean.UserSessionManagerBean;
import org.primefaces.component.chart.series.ChartSeries;
import org.primefaces.model.chart.CartesianChartModel;
import session.stateless.AccessRoleSessionBeanLocal;
import session.stateless.EmployeeSessionBeanLocal;
import session.stateless.LogSessionBeanLocal;
import session.stateless.MessageSessionBeanLocal;
import session.stateless.ProductSessionBeanLocal;
import session.stateless.ProductionScheduleSessionBeanLocal;
import session.stateless.SalesForecastSessionBeanLocal;
import session.stateless.SalesHistorySessionBeanLocal;
import session.stateless.SalesOrderSessionBeanLocal;

@ManagedBean(name = "salesForecastManagerBean")
@RequestScoped
public class SalesForecastManagerBean {

    @ManagedProperty(value = "#{userSessionManagerBean}")
    private UserSessionManagerBean userSessionManagerBean;
    @EJB
    private SalesHistorySessionBeanLocal salesHistorySessionBeanLocal;
    @EJB
    private ProductSessionBeanLocal productSessionBeanLocal;
    @EJB
    private SalesForecastSessionBeanLocal salesForecastSessionBeanLocal;
    @EJB
    private SalesOrderSessionBeanLocal salesOrderSessionBeanLocal;
    @EJB
    private EmployeeSessionBeanLocal employeeSessionBeanLocal;
    @EJB
    private LogSessionBeanLocal logSessionBeanLocal;
    @EJB
    private MessageSessionBeanLocal messageSessionBeanLocal;
    @EJB
    private AccessRoleSessionBeanLocal accessRoleSessionBeanLocal;
    @EJB
    private ProductionScheduleSessionBeanLocal productionScheduleSessionBeanLocal;
    private String loadAddSalesForecast;
    private String loadSimpleForecast;
    private String loadRegressionForecast;
    private String loadSearchConsolidatedMthSalesFc;
    private String loadSearchSalesForecast;
    private String loadUpdateForecast;
    private ArrayList<Product> products = new ArrayList<Product>();
    private ArrayList<SalesHistory> salesHistories = new ArrayList<SalesHistory>();
    private CartesianChartModel model = new CartesianChartModel();
    private Product selectedProduct = new Product();
    private Product selectedProductR = new Product();
    private String period;
    private String aggregate;
    private String trend = "0";
    private String trendMovement = "1";
    private String forecastYear;
    private DateFormat df = new SimpleDateFormat("dd-MM-yyyy");
    private String selectedMonth;
    private ArrayList<SalesForecast> salesForecasts = new ArrayList<SalesForecast>();
    private String remark;
    private Integer quantity = 0;
    private SalesForecast selectedForecast;
    private Boolean addMonth = false;
    private Boolean addQuarter = false;
    private Boolean addYear = false;
    private String filepath1 = "C:\\";
    private String filepath2 = "";
    private String filepath3 = "";
    private Regression regression;
    private Integer numberOfVariable;
    private Double x1 = 0.0;
    private Double x2 = 0.0;
    private Double x3 = 0.0;
    private Boolean hasX1 = false;
    private Boolean hasX2 = false;
    private Boolean hasX3 = false;
    private String x1_str;
    private String x2_str;
    private String x3_str;
    private String linearEquation;
    private String result;
    private double[] coeff;
    private String startYear;
    private String currentYear;
    private ConsolidatedMthSalesFc consolidatedMthSalesFc;
    private SalesForecast salesForecast;
    private List<ConsolidatedMthSalesFc> consolidatedMthSalesFcs;
    private Integer salesMeanHistory;
    private Integer salesTotalHistory;
    private Integer salesMedianHistory;
    private Boolean canSubmit = true;
    private Boolean isProcess = true;
    private Boolean isFinalize = true;
    private ArrayList<ProductionSchedule> productionSchedules;
    private ArrayList<ProductionScheduleDay> productionScheduleDays = new ArrayList<ProductionScheduleDay>();
    private ArrayList<Integer> sma = new ArrayList<Integer>();
    private String request;
    private Double aveUtilization;
    private Integer line;

    public String getLoadAddSalesForecast() {

        products = new ArrayList(productSessionBeanLocal.getProducts());
        Date date = Calendar.getInstance().getTime();
        String dateOfFc = df.format(date);
        String str[] = dateOfFc.split("-");
        Integer fcy = Integer.parseInt(str[2]) + 1;
        forecastYear = fcy.toString();
        return null;
    }

    public String getLoadSimpleForecast() {

        try {
            Date date = Calendar.getInstance().getTime();
            String dateOfFc = df.format(date);
            String str[] = dateOfFc.split("-");
            Integer fcy = Integer.parseInt(str[2]) + 1;
            forecastYear = fcy.toString();
            salesHistories = (ArrayList<SalesHistory>) userSessionManagerBean.getSelectedItem();
            if (userSessionManagerBean.getSalesForecasts() != null) //user planning the forecast 
            {
                salesForecasts = userSessionManagerBean.getSalesForecasts();
            }

            ArrayList<String> parameters = (ArrayList<String>) userSessionManagerBean.getParameters();
            selectedProduct = productSessionBeanLocal.getProduct(parameters.get(0));
            trend = parameters.get(1);
            trendMovement = parameters.get(2);
            aggregate = parameters.get(3);
            period = parameters.get(4);
            fcy--;
            currentYear = fcy.toString();
            fcy -= Integer.parseInt(period);
            startYear = fcy.toString();



            if (aggregate.compareTo("Month") == 0) {
                addMonth = true;
            } else if (aggregate.compareTo("Quarter") == 0) {
                addQuarter = true;
            } else {
                addYear = true;
            }

            drawHistoryGraph();
            drawGrowthGraph();
            drawForecastGraph();
            computeStatistics();

        } catch (Exception exception) {
            System.out.println(exception.toString());
            try {

                FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                        + userSessionManagerBean.getServerName() + ":"
                        + userSessionManagerBean.getServerPort()
                        + "/MerlionERP-war/Web_Production/addSalesForecast.xhtml");
            } catch (Exception ex) {
            }
        }


        return null;
    }

    public String getLoadRegressionForecast() {

        Date date = Calendar.getInstance().getTime();
        String dateOfFc = df.format(date);
        String str[] = dateOfFc.split("-");
        Integer fcy = Integer.parseInt(str[2]) + 1;
        forecastYear = fcy.toString();
        fcy--;
        currentYear = fcy.toString();
        aggregate = "Month";



        ArrayList<String> parameters = (ArrayList<String>) userSessionManagerBean.getParameters();
        selectedProductR = productSessionBeanLocal.getProduct(parameters.get(0));
        regression = userSessionManagerBean.getSelectedRegression();

        setNumberOfVariable((Integer) Integer.parseInt(parameters.get(1)));

        if (numberOfVariable > 0) {
            x1_str = parameters.get(2);
            hasX1 = true;
        }
        if (numberOfVariable > 1) {
            x2_str = parameters.get(3);
            hasX2 = true;
        }
        if (numberOfVariable > 2) {
            x3_str = parameters.get(4);
            hasX3 = true;
        }

        salesHistories = (ArrayList<SalesHistory>) userSessionManagerBean.getSelectedItem();
        salesForecasts = userSessionManagerBean.getSalesForecasts();
        drawHistoryGraph();
        drawForecastGraph();
        computeStatistics();
        findEquation();

        return null;
    }

    public String getLoadSearchSalesForecast() {
        salesForecasts = salesForecastSessionBeanLocal.getSalesForecasts("Initial production schedule");
        ArrayList sfcs = new ArrayList<SalesForecast>();

        for (SalesForecast sfc : salesForecasts) {
            if (getSalesHistories(sfc.getSalesMonth(), sfc.getSalesYear(), sfc.getProduct().getCode()) != null) {
                sfcs.add(sfc);
            }

        }
        salesForecasts = new ArrayList(sfcs);
        sfcs.clear();
        Collections.sort(salesForecasts);
        for (int i = 1; i < 13; i++) {
            for (SalesForecast sfc : salesForecasts) {
                if (sfc.getSalesMonth().compareTo(i) == 0) {
                    sfcs.add(sfc);
                }
            }
        }
        salesForecasts = new ArrayList(sfcs);

        return null;
    }

    public String getLoadSearchConsolidatedMthSalesFc() {


        String temp = (String) FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap().get("request");


        if (temp != null) {

            userSessionManagerBean.setSelectedItem((String) temp + ".xhtml");

            try {

                FacesContext.getCurrentInstance().getExternalContext().redirect("http://" + userSessionManagerBean.getServerName() + ":"
                        + userSessionManagerBean.getServerPort() + "/MerlionERP-war/Web_Production/searchConsolidatedMthSalesFc.xhtml");

            } catch (Exception ex) {
            }
        }


        request = (String) userSessionManagerBean.getSelectedItem();
        Date date = Calendar.getInstance().getTime();
        String dateOfFc = df.format(date);
        String str[] = dateOfFc.split("-");
        Integer fcy = Integer.parseInt(str[2]) + 1;
        consolidatedMthSalesFcs = salesForecastSessionBeanLocal.getConsolidatedMontlySalesForecast(fcy);


        if (request.compareTo("Web_Production/addProductionSchedule_ph.xhtml") == 0) {
            canSubmit = false;
            isFinalize = false;
            for (ConsolidatedMthSalesFc cmsfc : consolidatedMthSalesFcs) {
                if (cmsfc.getStatus().compareTo("Submitted to production") != 0) {
                    isProcess = false;
                }
            }


        } else if (request.compareTo("Web_Production/updateProductionSchedule_up.xhtml") == 0) {
            isProcess = false;
            canSubmit = false;
            for (ConsolidatedMthSalesFc cmsfc : consolidatedMthSalesFcs) {
                if (cmsfc.getStatus().compareTo("Initial production schedule") != 0 && cmsfc.getStatus().compareTo("Sales forecast adjusted") != 0) {
                    isFinalize = false;
                }
            }
        } else {

            isProcess = false;
            isFinalize = false;
            for (ConsolidatedMthSalesFc cmsfc : consolidatedMthSalesFcs) {
                if (cmsfc.getStatus().compareTo("Initial sales forecast") != 0) {
                    canSubmit = false;
                }
            }



        }





        return null;
    }

    public String getLoadUpdateForecast() {

        System.out.println("TEST");

        salesForecast = (SalesForecast) userSessionManagerBean.getSelectedItem();
        salesHistories = getSalesHistories(salesForecast.getSalesMonth(), salesForecast.getSalesYear(), salesForecast.getProduct().getCode());
        setProductionSchedules(productionScheduleSessionBeanLocal.getProductionSchedules(salesForecast.getSalesMonth(), salesForecast.getSalesYear()));

        HashMap hashProduce = new HashMap();
        line = 0;
        aveUtilization = 0.0;
        for (Product product : productSessionBeanLocal.getProducts()) {
            hashProduce.put(product.getCode(), 0);
        }
        for (ProductionSchedule ps : productionSchedules) {
            for (ProductionScheduleDay psd : ps.getProductionScheduleDays()) {
                int qty = ((Integer) (hashProduce.get(psd.getProduct().getCode())));
                qty += psd.getQuantity();
                hashProduce.put(psd.getProduct().getCode(), qty);

            }
            aveUtilization += ps.getUtilizationRate();
            line++;
        }
        productionScheduleDays.clear();
        aveUtilization = round(aveUtilization / line, 2);


        for (Product product : productSessionBeanLocal.getProducts()) {
            ProductionScheduleDay psd = new ProductionScheduleDay();
            psd.setProduct(product);
            psd.setQuantity((Integer) (hashProduce.get(psd.getProduct().getCode())));
            productionScheduleDays.add(psd);
            if (product.getCode().compareTo(salesForecast.getProduct().getCode()) == 0) {
                salesForecast.setQuantity(psd.getQuantity());
            }
        }
        drawDemandGraph();
        drawSimpleMovingAveGraph();
        drawProductionGraph();
        computeStatistics();

        return null;
    }

    public ArrayList<SalesHistory> getSalesHistories(Integer month, Integer year, String code) {
        try {
            ArrayList<SalesHistory> shs = new ArrayList<SalesHistory>();
            for (int i = 0; i < 6; i++) {
                month--;
                if (month == 0) {
                    year--;
                    month = 12;
                }
                shs.add(salesHistorySessionBeanLocal.getSalesHistory(month, year, code));
            }
            int low = 0;
            int smaValue = 0;
            ArrayList<SalesHistory> temp_shs = new ArrayList<SalesHistory>();
            for (int i = 0; i < 4; i++) {

                for (int x = 0; x < 3; x++) {

                    smaValue += shs.get(low).getQuantity();
                    low++;

                }

                sma.add(smaValue / 3);
                smaValue = 0;
                low -= 2;
                if (i != 3) {
                    temp_shs.add(shs.get(i));
                }
            }
            shs.clear();
            shs = new ArrayList(temp_shs);
            return shs;
        } catch (Exception ex) {
            return null;
        }
    }

    //<editor-fold defaultstate="collapsed" desc="Customer attributes. Click on the + sign on the left to edit the code.">
    /**
     * @return the userSessionManagerBean
     */
    public UserSessionManagerBean getUserSessionManagerBean() {
        return userSessionManagerBean;
    }

    /**
     * @param userSessionManagerBean the userSessionManagerBean to set
     */
    public void setUserSessionManagerBean(UserSessionManagerBean userSessionManagerBean) {
        this.userSessionManagerBean = userSessionManagerBean;
    }

    /**
     * @return the salesHistorySessionBeanLocal
     */
    public SalesHistorySessionBeanLocal getSalesHistorySessionBeanLocal() {
        return salesHistorySessionBeanLocal;
    }

    /**
     * @param salesHistorySessionBeanLocal the salesHistorySessionBeanLocal to set
     */
    public void setSalesHistorySessionBeanLocal(SalesHistorySessionBeanLocal salesHistorySessionBeanLocal) {
        this.salesHistorySessionBeanLocal = salesHistorySessionBeanLocal;
    }

    /**
     * @return the productSessionBeanLocal
     */
    public ProductSessionBeanLocal getProductSessionBeanLocal() {
        return productSessionBeanLocal;
    }

    /**
     * @param productSessionBeanLocal the productSessionBeanLocal to set
     */
    public void setProductSessionBeanLocal(ProductSessionBeanLocal productSessionBeanLocal) {
        this.productSessionBeanLocal = productSessionBeanLocal;
    }

    /**
     * @return the salesForecastSessionBeanLocal
     */
    public SalesForecastSessionBeanLocal getSalesForecastSessionBeanLocal() {
        return salesForecastSessionBeanLocal;
    }

    /**
     * @param salesForecastSessionBeanLocal the salesForecastSessionBeanLocal to set
     */
    public void setSalesForecastSessionBeanLocal(SalesForecastSessionBeanLocal salesForecastSessionBeanLocal) {
        this.salesForecastSessionBeanLocal = salesForecastSessionBeanLocal;
    }

    /**
     * @return the salesOrderSessionBeanLocal
     */
    public SalesOrderSessionBeanLocal getSalesOrderSessionBeanLocal() {
        return salesOrderSessionBeanLocal;
    }

    /**
     * @param salesOrderSessionBeanLocal the salesOrderSessionBeanLocal to set
     */
    public void setSalesOrderSessionBeanLocal(SalesOrderSessionBeanLocal salesOrderSessionBeanLocal) {
        this.salesOrderSessionBeanLocal = salesOrderSessionBeanLocal;
    }

    /**
     * @param loadAddSalesForecast the loadAddSalesForecast to set
     */
    public void setLoadAddSalesForecast(String loadAddSalesForecast) {
        this.loadAddSalesForecast = loadAddSalesForecast;
    }

    /**
     * @param loadSimpleForecast the loadSimpleForecast to set
     */
    public void setLoadSimpleForecast(String loadSimpleForecast) {
        this.loadSimpleForecast = loadSimpleForecast;
    }

    /**
     * @param loadRegressionForecast the loadRegressionForecast to set
     */
    public void setLoadRegressionForecast(String loadRegressionForecast) {
        this.loadRegressionForecast = loadRegressionForecast;
    }

    /**
     * @return the products
     */
    public ArrayList<Product> getProducts() {
        return products;
    }

    /**
     * @param products the products to set
     */
    public void setProducts(ArrayList<Product> products) {
        this.products = products;
    }

    /**
     * @return the salesHistories
     */
    public ArrayList<SalesHistory> getSalesHistories() {
        return salesHistories;
    }

    /**
     * @param salesHistories the salesHistories to set
     */
    public void setSalesHistories(ArrayList<SalesHistory> salesHistories) {
        this.salesHistories = salesHistories;
    }

    /**
     * @return the model
     */
    public CartesianChartModel getModel() {
        return model;
    }

    /**
     * @param model the model to set
     */
    public void setModel(CartesianChartModel model) {
        this.model = model;
    }

    /**
     * @return the selectedProduct
     */
    public Product getSelectedProduct() {
        return selectedProduct;
    }

    /**
     * @param selectedProduct the selectedProduct to set
     */
    public void setSelectedProduct(Product selectedProduct) {
        this.selectedProduct = selectedProduct;
    }

    /**
     * @return the period
     */
    public String getPeriod() {
        return period;
    }

    /**
     * @param period the period to set
     */
    public void setPeriod(String period) {
        this.period = period;
    }

    /**
     * @return the aggregate
     */
    public String getAggregate() {
        return aggregate;
    }

    /**
     * @param aggregate the aggregate to set
     */
    public void setAggregate(String aggregate) {
        this.aggregate = aggregate;
    }

    /**
     * @return the trend
     */
    public String getTrend() {
        return trend;
    }

    /**
     * @param trend the trend to set
     */
    public void setTrend(String trend) {
        this.trend = trend;
    }

    /**
     * @return the trendMovement
     */
    public String getTrendMovement() {
        return trendMovement;
    }

    /**
     * @param trendMovement the trendMovement to set
     */
    public void setTrendMovement(String trendMovement) {
        this.trendMovement = trendMovement;
    }

    /**
     * @return the currentYear
     */
    public String getForecastYear() {
        return forecastYear;
    }

    /**
     * @param currentYear the currentYear to set
     */
    public void setForecastYear(String forecastYear) {
        this.forecastYear = forecastYear;
    }

    /**
     * @return the df
     */
    public DateFormat getDf() {
        return df;
    }

    /**
     * @param df the df to set
     */
    public void setDf(DateFormat df) {
        this.df = df;
    }

    /**
     * @return the selectedMonth
     */
    public String getSelectedMonth() {
        return selectedMonth;
    }

    /**
     * @param selectedMonth the selectedMonth to set
     */
    public void setSelectedMonth(String selectedMonth) {
        this.selectedMonth = selectedMonth;
    }

    /**
     * @return the salesForecasts
     */
    public ArrayList<SalesForecast> getSalesForecasts() {
        return salesForecasts;
    }

    /**
     * @param salesForecasts the salesForecasts to set
     */
    public void setSalesForecasts(ArrayList<SalesForecast> salesForecasts) {
        this.salesForecasts = salesForecasts;
    }

    /**
     * @return the remark
     */
    public String getRemark() {
        return remark;
    }

    /**
     * @param remark the remark to set
     */
    public void setRemark(String remark) {
        this.remark = remark;
    }

    /**
     * @return the selectedForecast
     */
    public SalesForecast getSelectedForecast() {
        return selectedForecast;
    }

    /**
     * @param selectedForecast the selectedForecast to set
     */
    public void setSelectedForecast(SalesForecast selectedForecast) {
        this.selectedForecast = selectedForecast;
    }

    /**
     * @return the addMonth
     */
    public Boolean getAddMonth() {
        return addMonth;
    }

    /**
     * @param addMonth the addMonth to set
     */
    public void setAddMonth(Boolean addMonth) {
        this.addMonth = addMonth;
    }

    /**
     * @return the addQuarter
     */
    public Boolean getAddQuarter() {
        return addQuarter;
    }

    /**
     * @param addQuarter the addQuarter to set
     */
    public void setAddQuarter(Boolean addQuarter) {
        this.addQuarter = addQuarter;
    }

    /**
     * @return the addYear
     */
    public Boolean getAddYear() {
        return addYear;
    }

    /**
     * @param addYear the addYear to set
     */
    public void setAddYear(Boolean addYear) {
        this.addYear = addYear;
    }

    /**
     * @return the filepath1
     */
    public String getFilepath1() {
        return filepath1;
    }

    /**
     * @param filepath1 the filepath1 to set
     */
    public void setFilepath1(String filepath1) {
        this.filepath1 = filepath1;
    }

    /**
     * @return the filepath2
     */
    public String getFilepath2() {
        return filepath2;
    }

    /**
     * @param filepath2 the filepath2 to set
     */
    public void setFilepath2(String filepath2) {
        this.filepath2 = filepath2;
    }

    /**
     * @return the filepath3
     */
    public String getFilepath3() {
        return filepath3;
    }

    /**
     * @param filepath3 the filepath3 to set
     */
    public void setFilepath3(String filepath3) {
        this.filepath3 = filepath3;
    }

    /**
     * @return the numberOfVariable
     */
    public Integer getNumberOfVariable() {
        return numberOfVariable;
    }

    /**
     * @param numberOfVariable the numberOfVariable to set
     */
    public void setNumberOfVariable(Integer numberOfVariable) {
        this.numberOfVariable = numberOfVariable;
    }

    /**
     * @return the x1
     */
    public Double getX1() {
        return x1;
    }

    /**
     * @param x1 the x1 to set
     */
    public void setX1(Double x1) {
        this.x1 = x1;
    }

    /**
     * @return the x2
     */
    public Double getX2() {
        return x2;
    }

    /**
     * @param x2 the x2 to set
     */
    public void setX2(Double x2) {
        this.x2 = x2;
    }

    /**
     * @return the x3
     */
    public Double getX3() {
        return x3;
    }

    /**
     * @param x3 the x3 to set
     */
    public void setX3(Double x3) {
        this.x3 = x3;
    }

    /**
     * @return the hasX1
     */
    public Boolean getHasX1() {
        return hasX1;
    }

    /**
     * @param hasX1 the hasX1 to set
     */
    public void setHasX1(Boolean hasX1) {
        this.hasX1 = hasX1;
    }

    /**
     * @return the hasX2
     */
    public Boolean getHasX2() {
        return hasX2;
    }

    /**
     * @param hasX2 the hasX2 to set
     */
    public void setHasX2(Boolean hasX2) {
        this.hasX2 = hasX2;
    }

    /**
     * @return the hasX3
     */
    public Boolean getHasX3() {
        return hasX3;
    }

    /**
     * @param hasX3 the hasX3 to set
     */
    public void setHasX3(Boolean hasX3) {
        this.hasX3 = hasX3;
    }

    /**
     * @return the x1_str
     */
    public String getX1_str() {
        return x1_str;
    }

    /**
     * @param x1_str the x1_str to set
     */
    public void setX1_str(String x1_str) {
        this.x1_str = x1_str;
    }

    /**
     * @return the x2_str
     */
    public String getX2_str() {
        return x2_str;
    }

    /**
     * @param x2_str the x2_str to set
     */
    public void setX2_str(String x2_str) {
        this.x2_str = x2_str;
    }

    /**
     * @return the x3_str
     */
    public String getX3_str() {
        return x3_str;
    }

    /**
     * @param x3_str the x3_str to set
     */
    public void setX3_str(String x3_str) {
        this.x3_str = x3_str;
    }

    /**
     * @return the linearEquation
     */
    public String getLinearEquation() {
        return linearEquation;
    }

    /**
     * @param linearEquation the linearEquation to set
     */
    public void setLinearEquation(String linearEquation) {
        this.linearEquation = linearEquation;
    }

    /**
     * @return the result
     */
    public String getResult() {
        return result;
    }

    /**
     * @param result the result to set
     */
    public void setResult(String result) {
        this.result = result;
    }

    /**
     * @return the selectedProductR
     */
    public Product getSelectedProductR() {
        return selectedProductR;
    }

    /**
     * @param selectedProductR the selectedProductR to set
     */
    public void setSelectedProductR(Product selectedProductR) {
        this.selectedProductR = selectedProductR;
    }

    /**
     * @return the startYear
     */
    public String getStartYear() {
        return startYear;
    }

    /**
     * @param startYear the startYear to set
     */
    public void setStartYear(String startYear) {
        this.startYear = startYear;
    }

    /**
     * @return the currentYear
     */
    public String getCurrentYear() {
        return currentYear;
    }

    /**
     * @param currentYear the currentYear to set
     */
    public void setCurrentYear(String currentYear) {
        this.currentYear = currentYear;
    }

    /**
     * @return the quantity
     */
    public Integer getQuantity() {
        return quantity;
    }

    /**
     * @param quantity the quantity to set
     */
    public void setQuantity(Integer quantity) {
        this.quantity = quantity;
    }

    /**
     * @param loadSearchConsolidatedMthSalesFc the loadSearchConsolidatedMthSalesFc to set
     */
    public void setLoadSearchConsolidatedMthSalesFc(String loadSearchConsolidatedMthSalesFc) {
        this.loadSearchConsolidatedMthSalesFc = loadSearchConsolidatedMthSalesFc;
    }

    /**
     * @return the consolidatedMthSalesFc
     */
    public ConsolidatedMthSalesFc getConsolidatedMthSalesFc() {
        return consolidatedMthSalesFc;
    }

    /**
     * @param consolidatedMthSalesFc the consolidatedMthSalesFc to set
     */
    public void setConsolidatedMthSalesFc(ConsolidatedMthSalesFc consolidatedMthSalesFc) {
        this.consolidatedMthSalesFc = consolidatedMthSalesFc;
    }

    /**
     * @return the consolidatedMthSalesFcs
     */
    public List<ConsolidatedMthSalesFc> getConsolidatedMthSalesFcs() {
        return consolidatedMthSalesFcs;
    }

    /**
     * @param consolidatedMthSalesFcs the consolidatedMthSalesFcs to set
     */
    public void setConsolidatedMthSalesFcs(ArrayList<ConsolidatedMthSalesFc> consolidatedMthSalesFcs) {
        this.consolidatedMthSalesFcs = consolidatedMthSalesFcs;
    }

    /**
     * @param loadSearchSalesForecast the loadSearchSalesForecast to set
     */
    public void setLoadSearchSalesForecast(String loadSearchSalesForecast) {
        this.loadSearchSalesForecast = loadSearchSalesForecast;
    }

    /**
     * @return the salesForecast
     */
    public SalesForecast getSalesForecast() {
        return salesForecast;
    }

    /**
     * @param salesForecast the salesForecast to set
     */
    public void setSalesForecast(SalesForecast salesForecast) {
        this.salesForecast = salesForecast;
    }

    /**
     * @return the salesMeanHistory
     */
    public Integer getSalesMeanHistory() {
        return salesMeanHistory;
    }

    /**
     * @param salesMeanHistory the salesMeanHistory to set
     */
    public void setSalesMeanHistory(Integer salesMeanHistory) {
        this.salesMeanHistory = salesMeanHistory;
    }

    /**
     * @return the salesTotalHistory
     */
    public Integer getSalesTotalHistory() {
        return salesTotalHistory;
    }

    /**
     * @param salesTotalHistory the salesTotalHistory to set
     */
    public void setSalesTotalHistory(Integer salesTotalHistory) {
        this.salesTotalHistory = salesTotalHistory;
    }

    /**
     * @return the salesMedianHistory
     */
    public Integer getSalesMedianHistory() {
        return salesMedianHistory;
    }

    /**
     * @param salesMedianHistory the salesMedianHistory to set
     */
    public void setSalesMedianHistory(Integer salesMedianHistory) {
        this.salesMedianHistory = salesMedianHistory;
    }

    /**
     * @return the canSubmit
     */
    public Boolean getCanSubmit() {
        return canSubmit;
    }

    /**
     * @param canSubmit the canSubmit to set
     */
    public void setCanSubmit(Boolean canSubmit) {
        this.canSubmit = canSubmit;
    }

    /**
     * @param loadUpdateForecast the loadUpdateForecast to set
     */
    public void setLoadUpdateForecast(String loadUpdateForecast) {
        this.loadUpdateForecast = loadUpdateForecast;
    }

    /**
     * @return the isProcess
     */
    public Boolean getIsProcess() {
        return isProcess;
    }

    /**
     * @param isProcess the isProcess to set
     */
    public void setIsProcess(Boolean isProcess) {
        this.isProcess = isProcess;
    }

    /**
     * @return the productionSchedules
     */
    public ArrayList<ProductionSchedule> getProductionSchedules() {
        return productionSchedules;
    }

    /**
     * @param productionSchedules the productionSchedules to set
     */
    public void setProductionSchedules(ArrayList<ProductionSchedule> productionSchedules) {
        this.productionSchedules = productionSchedules;
    }

    /**
     * @return the productionScheduleDays
     */
    public ArrayList<ProductionScheduleDay> getProductionScheduleDays() {
        return productionScheduleDays;
    }

    /**
     * @param productionScheduleDays the productionScheduleDays to set
     */
    public void setProductionScheduleDays(ArrayList<ProductionScheduleDay> productionScheduleDays) {
        this.productionScheduleDays = productionScheduleDays;
    }

    /**
     * @return the aveUtilization
     */
    public Double getAveUtilization() {
        return aveUtilization;
    }

    /**
     * @param aveUtilization the aveUtilization to set
     */
    public void setAveUtilization(Double aveUtilization) {
        this.aveUtilization = aveUtilization;
    }

    /**
     * @return the line
     */
    public Integer getLine() {
        return line;
    }

    /**
     * @param line the line to set
     */
    public void setLine(Integer line) {
        this.line = line;
    }

    /**
     * @return the isFinalize
     */
    public Boolean getIsFinalize() {
        return isFinalize;
    }

    /**
     * @param isFinalize the isFinalize to set
     */
    public void setIsFinalize(Boolean isFinalize) {
        this.isFinalize = isFinalize;
    }

    //</editor-fold>
    public void addSimple(ActionEvent event) {

        int selectedYear = Integer.parseInt(forecastYear) - 1; //default to use this year record to FC
        selectedYear -= Integer.parseInt(period);

        for (SalesHistory sh : salesHistorySessionBeanLocal.getSalesHistories(selectedProduct.getCode())) {
            if (sh.getSalesYear() >= selectedYear) {
                salesHistories.add(sh);
            }
        }

        Collections.sort(salesHistories);


        ArrayList<String> parameters = new ArrayList<String>();
        parameters.add(selectedProduct.getCode());
        parameters.add(trend);
        parameters.add(trendMovement);
        parameters.add(aggregate);
        parameters.add(period);
        userSessionManagerBean.setRequest("simpleForecast.xhtml");

        salesForecasts = salesForecastSessionBeanLocal.getSalesForecasts(Integer.parseInt(forecastYear), selectedProduct.getCode());
        if (salesForecasts == null) {
            salesForecasts = userSessionManagerBean.getSalesForecasts();
        }


        aggregateSalesHistories();
        if (aggregate.compareTo("Month") != 0) {
            aggregateSalesForecasts();
        }

        userSessionManagerBean.setSalesForecasts(salesForecasts);
        userSessionManagerBean.setSelectedItem(salesHistories);
        userSessionManagerBean.setParameters(parameters);

        Boolean found = false;
        if (salesForecasts != null) {

            for (SalesForecast sfc : salesForecasts) {
                System.out.println(sfc);
                if (sfc.getStatus() != null) {
                    if (sfc.getStatus().compareTo("Initial sales forecast") != 0) {
                        found = true;
                    }
                }
            }
        }

        if (!found) {
            try {
                FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                        + userSessionManagerBean.getServerName() + ":"
                        + userSessionManagerBean.getServerPort()
                        + "/MerlionERP-war/Web_Production/simpleForecast.xhtml");

            } catch (Exception ex) {
            }
        } else {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Sales forecast for this month already exist.", ""));
        }

    }

    public void drawDemandGraph() {
        ChartSeries demandHistory = new ChartSeries();
        for (int i = salesHistories.size() - 1; i > -1; i--) {
            String salesRecordMonth = salesHistories.get(i).getSalesMonth().toString() + "/" + salesHistories.get(i).getSalesYear().toString();
            demandHistory.setLabel("Demand " + salesRecordMonth);
            demandHistory.set(salesRecordMonth, salesHistories.get(i).getQuantity());
            model.addSeries(demandHistory);
        }
    }

    public void drawSimpleMovingAveGraph() {

        ChartSeries sma_graph = new ChartSeries();
        for (int i = 0; i < 3; i++) {
            String salesRecordMonth = salesHistories.get(i).getSalesMonth().toString() + "/" + salesHistories.get(i).getSalesYear().toString();
            sma_graph.setLabel("Moving average " + salesRecordMonth);
            sma_graph.set(salesRecordMonth, sma.get(i + 1));
            model.addSeries(sma_graph);
        }
        String salesRecordMonth = salesForecast.getSalesMonth().toString() + "/" + salesForecast.getSalesYear().toString();
        sma_graph.setLabel("Forecasted Moving average " + salesRecordMonth);
        sma_graph.set(salesRecordMonth, sma.get(0));
        model.addSeries(sma_graph);
    }

    public void drawProductionGraph() {
        ChartSeries schedulePlot = new ChartSeries();
        String date = salesForecast.getSalesMonth().toString() + "/" + salesForecast.getSalesYear().toString();
        schedulePlot.setLabel("Production schedule");
        schedulePlot.set(date, salesForecast.getQuantity());
        model.addSeries(schedulePlot);
    }

    public void drawHistoryGraph() {
        ChartSeries demandCurrentYear = new ChartSeries();
        Collections.sort(salesHistories);
        for (int i = 0; i < salesHistories.size(); i++) {

            String salesRecordMonth = salesHistories.get(i).getSalesMonth().toString() + "/" + salesHistories.get(i).getSalesYear().toString();
            demandCurrentYear.setLabel("Historical data");
            demandCurrentYear.set(salesRecordMonth, salesHistories.get(i).getQuantity());
            model.addSeries(demandCurrentYear);
        }
    }

    public void drawForecastGraph() {


        Collections.sort(salesForecasts);
        ChartSeries forecast = new ChartSeries();
        forecast.setLabel("Historical data");
        forecast.set(salesHistories.get(salesHistories.size() - 1).getSalesMonth().toString() + "/" + salesHistories.get(salesHistories.size() - 1).getSalesYear().toString(), salesHistories.get(salesHistories.size() - 1).getQuantity());
        model.addSeries(forecast);
        for (SalesForecast fc : salesForecasts) {

            forecast.setLabel("Forecast (Plan) Sales " + forecastYear);
            forecast.set(fc.getSalesMonth().toString() + "/" + fc.getSalesYear().toString(), fc.getQuantity());
            model.addSeries(forecast);

        }
    }

    public void drawGrowthGraph() {

        ChartSeries demandForecastYear = new ChartSeries();

        if (Double.parseDouble(trend) != 0.0) {
            demandForecastYear.setLabel("Historical data");
            demandForecastYear.set(salesHistories.get(salesHistories.size() - 1).getSalesMonth().toString() + "/" + salesHistories.get(salesHistories.size() - 1).getSalesYear().toString(), salesHistories.get(salesHistories.size() - 1).getQuantity());
            model.addSeries(demandForecastYear);


            for (int i = 0; i < salesHistories.size(); i++) {
                String salesRecordMonth = salesHistories.get(i).getSalesMonth().toString() + "/" + forecastYear;
                demandForecastYear.setLabel("Predicted growth " + forecastYear);
                if (Integer.parseInt(trendMovement) == 1) {
                    Double actual = ((100 + Double.parseDouble(trend)) / 100);
                    demandForecastYear.set(salesRecordMonth, round((salesHistories.get(i).getQuantity()) * actual, 0));

                } else {
                    Double actual = ((100 - Double.parseDouble(trend)) / 100);
                    demandForecastYear.set(salesRecordMonth, round(salesHistories.get(i).getQuantity() * actual, 0));
                }


                model.addSeries(demandForecastYear);
            }

        }

    }

    public void computeStatistics() {
        setSalesTotalHistory((Integer) 0);

        ArrayList<Integer> monthlyDemands = new ArrayList<Integer>();
        ArrayList<Integer> monthlyForecasts = new ArrayList<Integer>();
        for (SalesHistory sh : salesHistories) {
            setSalesTotalHistory((Integer) (getSalesTotalHistory() + sh.getQuantity()));
            monthlyDemands.add(sh.getQuantity());
            monthlyForecasts.add(sh.getSalesYear());
        }
        Collections.sort(monthlyDemands);
        Collections.sort(monthlyForecasts);
        salesMeanHistory = salesTotalHistory / monthlyDemands.size();

        if (monthlyDemands.size() % 2 > 0) {
            int count = monthlyDemands.size() / 2;
            setSalesMedianHistory(monthlyDemands.get(count));

        } else {
            int count = salesHistories.size() / 2;
            setSalesMedianHistory((Integer) (monthlyDemands.get(count) + monthlyDemands.get(count - 1)) / 2);

        }

//        if (userSessionManagerBean.getRequest().compareTo("simpleForecast.xhtml") == 0) {
//            salesMeanTrend = salesTotalTrend / salesHistories.size();
//            temp_sales = new ArrayList<Double>();
//            for (SalesHistory sh : salesHistories) {
//                temp_sales.add((double) sh.getQuantity());
//            }
//            Collections.sort(temp_sales);
//
//            if (temp_sales.size() % 2 > 0) {
//                int count = temp_sales.size() / 2;
//                salesMedianTrend = temp_sales.get(count);
//            } else {
//                int count = salesHistories.size() / 2;
//                salesMedianTrend = (temp_sales.get(count) + temp_sales.get(count - 1)) / 2;
//
//            }
//
//            salesTotalTrend = round(salesTotalTrend, 2);
//            salesMeanTrend = round(salesMeanTrend, 2);
//            salesMedianTrend = round(salesMedianTrend, 2);
//            }
    }

    public double round(double valueToRound, int numberOfDecimalPlaces) {
        double multiplicationFactor = Math.pow(10, numberOfDecimalPlaces);
        double interestedInZeroDPs = valueToRound * multiplicationFactor;

        return Math.round(interestedInZeroDPs) / multiplicationFactor;
    }

    public void addForecastPlan(ActionEvent event) {
        try {


            Employee employee = employeeSessionBeanLocal.getEmployee(userSessionManagerBean.getUserId());
            SalesForecast sfc = new SalesForecast(Integer.parseInt(selectedMonth), Integer.parseInt(forecastYear), employee, selectedProduct, getQuantity(), remark, "Initial sales forecast", true);

            Boolean lock = false;
            for (SalesForecast fc : salesForecasts) {
                if (fc.getSalesMonth().compareTo(sfc.getSalesMonth()) == 0 && fc.getSalesYear().compareTo(sfc.getSalesYear()) == 0) {
                    selectedForecast = fc;
                    if (selectedForecast.getStatus() != null) {
                        if (selectedForecast.getStatus().compareTo("Submitted to production") == 0) {
                            lock = true;
                        }
                    }
                }
            }



            if (!lock) {
                salesForecasts.remove(selectedForecast);
                salesForecasts.add(sfc);
                userSessionManagerBean.setSalesForecasts(salesForecasts);

                try {

                    FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                            + userSessionManagerBean.getServerName() + ":"
                            + userSessionManagerBean.getServerPort()
                            + "/MerlionERP-war/Web_Production/simpleForecast.xhtml");
                } catch (Exception ex) {
                }
            } else {
                FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Sales forecast already submitted. Please contract production department to withdraw it manually", ""));

            }

        } catch (Exception ex) {
            System.out.println(ex.toString());
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "One or more fields filled in incorrectly.", ""));
        }
    }

    public void removeForecastPlan(ActionEvent event) {
        if (selectedForecast != null && selectedForecast.getStatus().compareTo("Initial sales plan") == 0) {


            salesForecasts.remove(selectedForecast);

            try {

                FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                        + userSessionManagerBean.getServerName() + ":"
                        + userSessionManagerBean.getServerPort()
                        + "/MerlionERP-war/Web_Production/simpleForecast.xhtml");
            } catch (Exception ex) {
            }
        } else {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "Unable to remove lock or null forecast.", ""));

        }
    }

    public void done(ActionEvent event) {

        try {


            if (aggregate.compareTo("Year") == 0 && salesForecasts.size() > 0) {

                Integer quantityPerMonth = 0;
                ArrayList<SalesForecast> salesRecords = new ArrayList<SalesForecast>();
                if (salesForecasts.get(0).getQuantity() > 0) {
                    quantityPerMonth = salesForecasts.get(0).getQuantity() / 12;
                } else {
                    quantityPerMonth = 0;
                }


                for (int i = 1; i < 13; i++) {
                    SalesForecast sfc = new SalesForecast(i, salesForecasts.get(0).getSalesYear(), salesForecasts.get(0).getSalesRep(), salesForecasts.get(0).getProduct(), quantityPerMonth, salesForecasts.get(0).getRemark(), "Initial sales forecast", true);
                    salesRecords.add(sfc);
                }

                salesForecasts = salesRecords;
            }
            if (aggregate.compareTo("Quarter") == 0) {
                ArrayList<SalesForecast> salesRecords = new ArrayList<SalesForecast>();
                for (SalesForecast sfc : salesForecasts) {
                    salesRecords = disaggregateQuarter(salesRecords, sfc);
                }
                salesForecasts = salesRecords;

            }
            salesForecastSessionBeanLocal.addSalesForecasts(salesForecasts, forecastYear, selectedProduct.getCode());
            ArrayList<String> al = new ArrayList<String>();
            al.add("Sales forecast updated");
            al.add("You have successfully updated the sales forecast. Other involved departments will be notified about the changes.");
            al.add("Click on the link to return to ");
            al.add("continue");
            al.add("Web_Production/addSalesForecast.xhtml");
            userSessionManagerBean.setSelectedItem(al);

            logSessionBeanLocal.addLog("Add sales forecast", "Sales forecast updated. Year:  " + forecastYear, "simpleForecast.xhtml", userSessionManagerBean.getUserId());


            FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                    + userSessionManagerBean.getServerName() + ":"
                    + userSessionManagerBean.getServerPort()
                    + "/MerlionERP-war/success.xhtml");
        } catch (Exception ex) {
            System.out.println(ex.toString());
        }

    }

    public ArrayList<SalesForecast> disaggregateQuarter(ArrayList<SalesForecast> salesRecords, SalesForecast sfc) {
        int count = 0;
        if (sfc.getSalesMonth() == 1) {
            count = 1;
        } else if (sfc.getSalesMonth() == 2) {
            count = 4;
        } else if (sfc.getSalesMonth() == 3) {
            count = 7;
        } else {
            count = 10;
        }

        Integer quantityPerMonth = 0;
        if (sfc.getQuantity() > 0) {
            quantityPerMonth = sfc.getQuantity() / 3;
        }



        for (int i = 0; i < 3; i++) {
            SalesForecast fc = new SalesForecast(count, sfc.getSalesYear(), sfc.getSalesRep(), sfc.getProduct(), quantityPerMonth, sfc.getRemark(), "Initial sales plan", true);
            salesRecords.add(fc);
            count++;
        }
        return salesRecords;
    }

    public void aggregateSalesHistories() {

        Collections.sort(salesHistories);
        int count = 0;
        int month = 1;


        if (aggregate.compareTo("Month") == 0) {
            count = 1;
        } else if (aggregate.compareTo("Quarter") == 0) {
            count = 3;
        } else {
            count = 12;
        }

        ArrayList<SalesHistory> salesRecords = new ArrayList<SalesHistory>();
        SalesHistory salesHistory = new SalesHistory();
        int i = 0;

        for (SalesHistory sh : salesHistories) {

            salesHistory.setSalesYear(sh.getSalesYear());
            salesHistory.setProduct(sh.getProduct());
            Integer current_quantity = salesHistory.getQuantity();
            current_quantity += sh.getQuantity();
            salesHistory.setQuantity(current_quantity);

            i++;
            if (i == count) {

                salesHistory.setSalesMonth(month);
                month++;
                salesRecords.add(salesHistory);
                salesHistory = new SalesHistory();
                i = 0;
                if (month == 5 && aggregate.compareTo("Quarter") == 0) {
                    month = 1;
                } else if (month == 2 && aggregate.compareTo("Year") == 0) {
                    month = 1;
                } else if (month == 13 && aggregate.compareTo("Month") == 0) {
                    month = 1;
                }
            }
        }
        salesHistories = salesRecords;
        Collections.sort(salesHistories);


    }

    public void aggregateSalesForecasts() {
        for (int z = 1; z < 13; z++) {
            Boolean found = false;
            for (SalesForecast sfc : salesForecasts) {
                if (sfc.getSalesMonth().compareTo(z) == 0) {
                    found = true;
                }
            }
            if (!found) {
                Employee employee = employeeSessionBeanLocal.getEmployee(userSessionManagerBean.getUserId());
                salesForecasts.add(new SalesForecast(z, Integer.parseInt(forecastYear), employee, selectedProduct, 0, null, "Initial sales forecast", true));



            }
        }

        Collections.sort(salesForecasts);



        int count = 0;
        int month = 1;
        if (aggregate.compareTo("Month") == 0) {
            count = 1;
        } else if (aggregate.compareTo("Quarter") == 0) {
            count = 3;
        } else {
            count = 12;
        }

        ArrayList<SalesForecast> salesRecords = new ArrayList<SalesForecast>();
        SalesForecast salesForecast = new SalesForecast();
        int i = 0;


        for (SalesForecast sf : salesForecasts) {

            salesForecast.setSalesYear(sf.getSalesYear());
            salesForecast.setProduct(sf.getProduct());
            Integer current_quantity = salesForecast.getQuantity();
            current_quantity += sf.getQuantity();

            salesForecast.setQuantity(current_quantity);
            salesForecast.setSalesRep(sf.getSalesRep());
            i++;
            if (i == count) {

                salesForecast.setSalesMonth(month);
                month++;
                salesRecords.add(salesForecast);
                salesForecast = new SalesForecast();
                i = 0;
                if (month == 5 && aggregate.compareTo("Quarter") == 0) {
                    month = 1;
                } else if (month == 2 && aggregate.compareTo("Year") == 0) {
                    month = 1;
                } else if (month == 13 && aggregate.compareTo("Month") == 0) {
                    month = 1;
                }

            }
        }
        salesForecasts = salesRecords;
        Collections.sort(salesForecasts);
    }

    public void addRegression(ActionEvent event) {

        ArrayList<IndependentVariable> independentVariables1 = null;
        ArrayList<IndependentVariable> independentVariables2 = null;
        ArrayList<IndependentVariable> independentVariables3 = null;
        ArrayList<IndependentVariable> selectedIndependentVariables = null;
        ArrayList<SalesHistory> selectedSalesHistories = null;

        Boolean fileSizeError = false;
        Boolean found = true;
        int count = 0;
        int size = 0;

        //read in file 1 if presented
        if (filepath1.compareTo("") != 0) {
            independentVariables1 = salesForecastSessionBeanLocal.getIndependentVariables(filepath1);            
            if (independentVariables1 != null) {
                selectedIndependentVariables = independentVariables1;
                size = independentVariables1.size();
                count++;
            }
        }

        //read in file 2 if presented
        if (filepath2.compareTo("") != 0) {
            independentVariables2 = salesForecastSessionBeanLocal.getIndependentVariables(filepath2);
            if (independentVariables2 != null) {
                if (selectedIndependentVariables == null) {
                    selectedIndependentVariables = independentVariables2;   //variable 2 is first available variable
                }
                count++;
                if (size != 0) {
                    if (size != independentVariables2.size()) {
                        fileSizeError = true;
                    } else {

                        boolean hasRecord = false;
                        for (IndependentVariable variable : selectedIndependentVariables) {
                            for (IndependentVariable var : independentVariables2) {
                                if (variable.getCollectedMonth() == var.getCollectedMonth() && variable.getCollectedYear() == var.getCollectedYear()) {
                                    hasRecord = true;
                                }
                            }
                            if (!hasRecord) {
                                found = false;
                            }
                        }
                    }

                } else {
                    size = independentVariables2.size();
                }
            }

        }

        //read in file 3 if presented


        if (filepath3.compareTo("") != 0) {
            independentVariables3 = salesForecastSessionBeanLocal.getIndependentVariables(filepath3);
            if (independentVariables3 != null) {
                if (selectedIndependentVariables == null) {
                    selectedIndependentVariables = independentVariables3;   //variable 2 is first available variable
                }
                if (size != 0) {
                    if (size != independentVariables3.size()) {
                        fileSizeError = true;
                    } else {
                        boolean hasRecord = false;
                        for (IndependentVariable variable : selectedIndependentVariables) {
                            for (IndependentVariable var : independentVariables3) {
                                if (variable.getCollectedMonth() == var.getCollectedMonth() && variable.getCollectedYear() == var.getCollectedYear()) {
                                    hasRecord = true;
                                }
                            }
                            if (!hasRecord) {
                                found = false;
                            }
                        }
                    }
                } else {
                    size = independentVariables3.size();
                }
            }
            count++;

        }
        //get historical records for the file presented
        selectedSalesHistories = salesHistorySessionBeanLocal.getSalesHistories(selectedIndependentVariables, selectedProductR.getCode());

        if (size != selectedSalesHistories.size()) {
            fileSizeError = true;
        }
        //If all file size tally, compute regression
        if (!fileSizeError && count != 0 && found) {
            double xData[][] = new double[count][size];
            count = 0;

            if (independentVariables1 != null) {
                Collections.sort(independentVariables1);

                for (int i = 0; i < independentVariables1.size(); i++) {

                    //read file 1 data into x0
                    xData[count][i] = independentVariables1.get(i).getTotalAmount();

                }
                count++;

            }
            if (independentVariables2 != null) {
                Collections.sort(independentVariables2);

                for (int i = 0; i < independentVariables2.size(); i++) {

                    //read file 1 data into x1, otherwise x0
                    xData[count][i] = independentVariables2.get(i).getTotalAmount();
                }
                count++;
            }
            if (independentVariables3 != null) {
                Collections.sort(independentVariables3);

                for (int i = 0; i < independentVariables3.size(); i++) {

                    //read file 1 data into x2, otherwise x0 or x1
                    xData[count][i] = independentVariables3.get(i).getTotalAmount();
                }
                count++;
            }


            double[] yData = new double[selectedSalesHistories.size()];
            int i = 0;

            for (SalesHistory sh : selectedSalesHistories) {

                //read historical data into y
                yData[i] = sh.getQuantity();
            }



            regression = new Regression(xData, yData);
            regression.linear();

            //check regression library against opensource code (only 1 variable)
            testRegression(yData, xData[0], size);


            ArrayList<String> parameters = new ArrayList<String>();
            parameters.add(selectedProductR.getCode()); //0
            parameters.add(((Integer) count).toString()); //1

            //store variables name into session
            if (independentVariables1 != null) {
                parameters.add(x1_str);
            }
            if (independentVariables2 != null) {
                parameters.add(x2_str);
            }
            if (independentVariables3 != null) {
                parameters.add(x3_str);
            }

            salesForecasts = salesForecastSessionBeanLocal.getSalesForecasts(Integer.parseInt(forecastYear), selectedProductR.getCode());
            if (salesForecasts == null) {
                salesForecasts = userSessionManagerBean.getSalesForecasts();
            }

            found = false;
            if (salesForecasts != null) {

                for (SalesForecast sfc : salesForecasts) {
                    if (sfc.getStatus().compareTo("Initial sales forecast") != 0) {
                        found = true;
                    }
                }
            }
            if (!found) {

                for (SalesHistory sh : salesHistorySessionBeanLocal.getSalesHistories(selectedProductR.getCode())) {
                    if (sh.getSalesYear() == (Integer.parseInt(forecastYear) - 1)) {
                        salesHistories.add(sh);
                    }
                }

                Collections.sort(salesHistories);
                salesHistories = checkData(salesHistories);



                userSessionManagerBean.setSalesForecasts(salesForecasts);
                userSessionManagerBean.setSelectedItem(salesHistories);
                userSessionManagerBean.setParameters(parameters);
                userSessionManagerBean.setSelectedRegression(regression);
                userSessionManagerBean.setRequest("regressionForecast.xhtml");

                try {
                    FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                            + userSessionManagerBean.getServerName() + ":"
                            + userSessionManagerBean.getServerPort()
                            + "/MerlionERP-war/Web_Production/regressionForecast.xhtml");

                } catch (Exception ex) {
                }

            } else {
                FacesContext.getCurrentInstance().addMessage(null,
                        new FacesMessage(FacesMessage.SEVERITY_ERROR, "Sales forecast for this month already exist.", ""));
            }
        } else {
            System.out.println("FILE SIZE ERROR:" + fileSizeError);
            System.out.println("RECORD NOT FOUND:" + !found);
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "File record mismatch.", ""));
        }
    }

    public void testRegression(double[] yData, double[] xData, int size) {

        int MAXN = size;
        int n = 0;
        double[] x = new double[MAXN];
        double[] y = new double[MAXN];

        double sumx = 0.0, sumy = 0.0, sumx2 = 0.0;
        int count = 1;
        // first pass: read in data, compute xbar and ybar

        for (int i = 0; i < size; i++) {
            x[n] = xData[i];
            y[n] = yData[i];
            sumx += x[n];
            sumx2 += x[n] * x[n];
            sumy += y[n];
            n++;
        }
        double xbar = sumx / n;
        double ybar = sumy / n;

        // second pass: compute summary statistics
        double xxbar = 0.0, yybar = 0.0, xybar = 0.0;
        for (int i = 0; i < n; i++) {
            xxbar += (x[i] - xbar) * (x[i] - xbar);
            yybar += (y[i] - ybar) * (y[i] - ybar);
            xybar += (x[i] - xbar) * (y[i] - ybar);
        }
        double beta1 = xybar / xxbar;
        double beta0 = ybar - beta1 * xbar;

        // print results
        System.out.println("y   = " + beta1 + " * x + " + beta0);

        // analyze results
        int df = n - 2;
        double rss = 0.0;      // residual sum of squares
        double ssr = 0.0;      // regression sum of squares
        for (int i = 0; i < n; i++) {
            double fit = beta1 * x[i] + beta0;
            rss += (fit - y[i]) * (fit - y[i]);
            ssr += (fit - ybar) * (fit - ybar);
        }
        double R2 = ssr / yybar;
        double svar = rss / df;
        double svar1 = svar / xxbar;
        double svar0 = svar / n + xbar * xbar * svar1;
        System.out.println("R^2                 = " + R2);
        System.out.println("std error of beta_1 = " + Math.sqrt(svar1));
        System.out.println("std error of beta_0 = " + Math.sqrt(svar0));
        svar0 = svar * sumx2 / (n * xxbar);
        System.out.println("std error of beta_0 = " + Math.sqrt(svar0));

        System.out.println("SSTO = " + yybar);
        System.out.println("SSE  = " + rss);
        System.out.println("SSR  = " + ssr);

    }

    public void findEquation() {

        coeff = regression.getBestEstimates();
        double[] pvalue = regression.getPvalues();
        double[] residuals = regression.getResiduals();
        double[] bestError = regression.getBestEstimatesErrors();

        linearEquation = "Y=";

        if (numberOfVariable > 0) {
            linearEquation += "X1 (" + round(coeff[1], 4) + ")";
        }
        if (numberOfVariable > 1) {
            linearEquation += " + X2 (" + round(coeff[2], 4) + ")";
        }
        if (numberOfVariable > 2) {
            linearEquation += " + X3 (" + round(coeff[3], 4) + ")";
        }
        linearEquation += " + " + round(coeff[0], 2);


        result = "Regression Statistics \n";
        result += "==================\n";

        if (numberOfVariable > 0) {
            result += x1_str + "\n";
            result += "Pvalue: " + round(pvalue[0], 2) + "\n";
            result += "Std error: " + round(bestError[0], 2) + "\n";
            result += "Residual: " + round(residuals[0], 2) + "\n";
            result += "* " + getIndicator(pvalue[0]) + "\n\n";

        }
        if (numberOfVariable > 1) {
            result += x2_str + "\n";
            result += "Pvalue: " + round(pvalue[1], 2) + "\n";
            result += "Std error: " + round(bestError[1], 2) + "\n";
            result += "Residual: " + round(residuals[1], 2) + "\n";
            result += "* " + getIndicator(pvalue[1]) + "\n\n";
        }
        if (numberOfVariable > 2) {
            result += x3_str + "\n";
            result += "Pvalue: " + round(pvalue[2], 2) + "\n";
            result += "Std error: " + round(bestError[2], 2) + "\n";
            result += "Residual: " + round(residuals[2], 2) + "\n";
            result += "* " + getIndicator(pvalue[2]) + "\n\n";
        }
        result += "==================\n";
        result += "R^2: " + round(regression.getCoefficientOfDetermination(), 2) + "\n";
        result += "Squares of residuals: " + round(regression.getSumOfSquares(), 2);


    }

    public String getIndicator(double pvalue) {
        if (pvalue > 0.1) {
            return "No evidence against the null hypothesis. (Extremely Weak Predictor)";
        } else if (pvalue > 0.05) {
            return "Weak evidence against the null hypothesis in favor of the alternative. (Weak Predictor) ";
        } else if (pvalue > 0.01) {
            return "Moderate evidence against the null hypothesis in favor of the alternative. (Moderate Predictor)";
        } else if (pvalue > 0.001) {
            return "Strong evidence against the null hypothesis in favor of the alternative. (Strong Predictor)";
        } else if (pvalue < 0.001) {
            return "Very strong evidence against the null hypothesis in favor of the alternative. (Extremely Strong Predictor)";
        } else {
            return "(Permissible value)";
        }
    }

    public void addForecastPlanRegression(ActionEvent event) {
        try {
            double salesForecastPlan = coeff[0];

            if (numberOfVariable > 0) {
                salesForecastPlan += (coeff[1] * x1);

            }
            if (numberOfVariable > 1) {
                salesForecastPlan += (coeff[2] * x1);
            }
            if (numberOfVariable > 2) {
                salesForecastPlan += (coeff[3] * x1);
            }

            salesForecastPlan = round(salesForecastPlan, 2);
            setQuantity((Integer) ((int) (salesForecastPlan / selectedProductR.getPrice())));


            Employee employee = employeeSessionBeanLocal.getEmployee(userSessionManagerBean.getUserId());
            SalesForecast sfc = new SalesForecast(Integer.parseInt(selectedMonth), Integer.parseInt(forecastYear), employee, selectedProductR, getQuantity(), remark, "Initial sales plan", true);

            for (SalesForecast fc : salesForecasts) {
                if (fc.getSalesMonth().compareTo(sfc.getSalesMonth()) == 0 && fc.getSalesYear().compareTo(sfc.getSalesYear()) == 0) {
                    selectedForecast = fc;
                }
            }
            salesForecasts.remove(selectedForecast);
            salesForecasts.add(sfc);
            userSessionManagerBean.setSalesForecasts(salesForecasts);

            try {

                FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                        + userSessionManagerBean.getServerName() + ":"
                        + userSessionManagerBean.getServerPort()
                        + "/MerlionERP-war/Web_Production/regressionForecast.xhtml");
            } catch (Exception ex) {
            }
        } catch (Exception ex) {
            FacesContext.getCurrentInstance().addMessage(null,
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, "One or more fields filled in incorrectly.", ""));
        }

    }

    public ArrayList<SalesHistory> checkData(ArrayList<SalesHistory> shs) {

        Boolean found = false;
        for (int i = 1; i < 13; i++) {
            for (SalesHistory sh : shs) {
                if (sh.getSalesMonth() == i) {
                    found = true;
                }
            }
            if (!found) {

                SalesHistory dummySH = new SalesHistory(i, Integer.parseInt(forecastYear) - 1, selectedProduct, 0);
                shs.add(dummySH);


            }
        }
        Collections.sort(shs);
        return shs;
    }

    public void processConsolidatedMthSalesFc(ActionEvent event) {
//        Integer count = 0;
//        for (ConsolidatedMthSalesFc cmsfc : consolidatedMthSalesFcs) {
//            if (cmsfc.getStatus().compareTo("Submitted to production") == 0) {
//                count++;
//            }
//        }
//
//        if (count > 0) {
        userSessionManagerBean.setSelectedItem(consolidatedMthSalesFcs);
        try {
            FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                    + userSessionManagerBean.getServerName() + ":"
                    + userSessionManagerBean.getServerPort()
                    + "/MerlionERP-war/Web_Production/addProductionSchedule_ph.xhtml");

        } catch (Exception ex) {
        }

//        } else {
//            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Sales forecast has been processed.", ""));
//        }


    }

    public void submitConsolidatedMthSalesFc(ActionEvent event) {


        Boolean incomplete = false;
        Integer size = productSessionBeanLocal.getProducts().size();

        for (ConsolidatedMthSalesFc cmsfc : consolidatedMthSalesFcs) {
            if (cmsfc.getSalesForecasts().size() < size)
            {
                incomplete = true;
            }
        }




        if (!incomplete)
        {
        Integer year = 0;
        for (ConsolidatedMthSalesFc cmsfc : consolidatedMthSalesFcs) {
            salesForecastSessionBeanLocal.updateSalesForecastStatus(cmsfc.getSalesYear(), cmsfc.getSalesMonth(), "Submitted to production", true);
            year = cmsfc.getSalesYear();
        }
        ArrayList<AccessRole> rlist = accessRoleSessionBeanLocal.getAccessRoles("Create Production Schedule");
        ArrayList<Employee> employees = employeeSessionBeanLocal.getEmployees(rlist);

        for (Employee em : employees) {
            Employee owner = employeeSessionBeanLocal.getEmployee("System");
            messageSessionBeanLocal.addMessage("System", em.getUserId(), "Sales forecast submitted",
                    "Sales forecast for Year: " + year + "</b> has been submitted. Please assess and create a production schedule for this forecast. "
                    + "<p><hr/><p>This is a system generated message, no reply is required.", owner);

            owner = employeeSessionBeanLocal.getEmployee(em.getUserId());
            messageSessionBeanLocal.addMessage("System", em.getUserId(), "Sales forecast submitted",
                    "Sales forecast for Year: " + year + "</b> has been submitted. Please assess and create a production schedule for this forecast. "
                    + "<p><hr/><p>This is a system generated message, no reply is required.", owner);
        }

        try {

            ArrayList<String> al = new ArrayList<String>();
            al.add("Sales forecast successfully submitted");
            al.add("You have successfully submitted the selected sales forecast for production plan.");
            al.add("Click on the link to return to ");
            al.add("continue");
            al.add("Web_Production/searchConsolidatedMthSalesFc.xhtml?request=searchConsolidatedMthSalesFc");
            userSessionManagerBean.setSelectedItem(al);


            logSessionBeanLocal.addLog("Submit sales forecast", "Sales forecast submitted Year: " + year, "searchSalesForecast.xhtml", userSessionManagerBean.getUserId());



            FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                    + userSessionManagerBean.getServerName() + ":"
                    + userSessionManagerBean.getServerPort()
                    + "/MerlionERP-war/success.xhtml");
        } catch (Exception ex) {
        }


    }
        else
        {
              FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Incomplete record.", ""));
        }
    }

    public void selectSalesForecast(ActionEvent event) {
        if (salesForecast != null) {
            try {
                userSessionManagerBean.setSelectedItem(salesForecast);
                FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                        + userSessionManagerBean.getServerName() + ":"
                        + userSessionManagerBean.getServerPort()
                        + "/MerlionERP-war/Web_Production/updateSalesForecast.xhtml");
            } catch (Exception ex) {
            }
        }

    }

    public void updateForecastPlan(ActionEvent event) {
        if (salesForecast != null && salesForecast.getQuantity() > 0) {

            salesForecastSessionBeanLocal.updateSalesForecastStatus(salesForecast.getSalesYear(), salesForecast.getSalesMonth(),
                    salesForecast.getProduct().getCode(), "Sales forecast adjusted", true);

            salesForecastSessionBeanLocal.addSalesForecast(salesForecast.getSalesMonth(), salesForecast.getSalesYear(),
                    userSessionManagerBean.getUserId(), salesForecast.getProduct().getCode(), salesForecast.getQuantity(),
                    salesForecast.getRemark(), "New sales forecast", true);




            try {
                ArrayList<String> al = new ArrayList<String>();
                al.add("Sales forecast successfully adjusted");
                al.add("You have successfully adjusted the selected sales forecast for production plan.");
                al.add("Click on the link to return to ");
                al.add("continue");
                al.add("Web_Production/searchSalesForecast.xhtml");
                userSessionManagerBean.setSelectedItem(al);


                FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                        + userSessionManagerBean.getServerName() + ":"
                        + userSessionManagerBean.getServerPort()
                        + "/MerlionERP-war/success.xhtml");
            } catch (Exception ex) {
                System.out.println(ex.toString());
            }


        } else {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Incomplete record.", ""));
        }
    }

    public void fianlizeConsolidatedMthSalesFc(ActionEvent event) {
        if (consolidatedMthSalesFc != null) {
            userSessionManagerBean.setSelectedItem(consolidatedMthSalesFcs);

            ArrayList<SalesForecast> sfcs = new ArrayList<SalesForecast>();
            for (SalesForecast sfc : consolidatedMthSalesFc.getSalesForecasts()) {
                if (sfc.getStatus().compareTo("New sales forecast") == 0) {
                    salesForecasts.add(sfc);
                } else {
                    sfcs.add(sfc);
                }
            }
            consolidatedMthSalesFc.setSalesForecasts(sfcs);
            userSessionManagerBean.setSalesForecasts(salesForecasts);

            userSessionManagerBean.setParameters(consolidatedMthSalesFc);
            userSessionManagerBean.setProductionSchedules(productionScheduleSessionBeanLocal.getProductionSchedules(consolidatedMthSalesFc.getSalesMonth(), consolidatedMthSalesFc.getSalesYear()));
            try {
                FacesContext.getCurrentInstance().getExternalContext().redirect("http://"
                        + userSessionManagerBean.getServerName() + ":"
                        + userSessionManagerBean.getServerPort()
                        + "/MerlionERP-war/Web_Production/updateProductionSchedule_up.xhtml");

            } catch (Exception ex) {
            }
        } else {
            FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Please select a record to finalize.", ""));
        }

    }
}
